# -*- coding: utf-8 -*-
'''
Created on 11/nov/2009

@author: sax
'''
from django import template
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.forms.formsets import all_valid
from django.forms.models import modelform_factory
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.utils.encoding import force_unicode
from django.utils.functional import curry
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
from xadmin import helpers
from xadmin.util import unquote, flatten_fieldsets

from xadmin.options.strategies import Strategy
class EditStrategy(Strategy):
    save_as = False
    save_on_top = False

    inlines = []
        
    inline_instances = ()
    declared_fieldsets = ()
    prepopulated_fields = {}
    
    change_form_template = None
    
    def __set__(self, owner, value):
        super(EditStrategy, self).__set__(owner, value)

    def get_form(self, request, obj=None, **kwargs):
        """
        Returns a Form class for use in the admin add view. This is used by
        add_view and change_view.
        """
        if self._owner.declared_fieldsets:
            fields = flatten_fieldsets(self.declared_fieldsets)
        else:
            fields = None
        if self._owner.exclude is None:
            exclude = []
        else:
            exclude = list(self._owner.exclude)
        # if exclude is an empty list we pass None to be consistant with the
        # default on modelform_factory
        defaults = {
            "form": self._owner.form,
            "fields": fields,
            "exclude": (exclude + kwargs.get("exclude", [])) or None,
            "formfield_callback": curry(self._owner.formfield_for_dbfield, request=request),
        }
        defaults.update(kwargs)
        return modelform_factory(self.model, **defaults)
    
    def get_formsets(self, request, obj=None):
        for inline in self.inline_instances:
            yield inline.get_formset(request, obj)        
    
    def get_fieldsets(self, request, obj=None):
        "Hook for specifying fieldsets for the add form."
        if self.declared_fieldsets:
            return self.declared_fieldsets
        form = self.get_form(request, obj)
        return [(None, {'fields': form.base_fields.keys()})]

    def process_POST(self, request):
        ModelForm = self.get_form(request)
        form = ModelForm(request.POST, request.FILES)
        if form.is_valid():
            form_validated = True
            new_object = self._owner.save_form(request, form, change=False)
        else:
            form_validated = False
            new_object = self.model()
        prefixes = {}
        for FormSet in self.get_formsets(request, None):
            prefix = FormSet.get_default_prefix()
            prefixes[prefix] = prefixes.get(prefix, 0) + 1
            if prefixes[prefix] != 1:
                prefix = "%s-%s" % (prefix, prefixes[prefix])
            formset = FormSet(data=request.POST, files=request.FILES,
                              instance=new_object, prefix=prefix,
                              save_as_new=request.POST.has_key("_saveasnew"),
                              )
            formsets.append(formset)
        return form_validated
#        if all_valid(formsets) and form_validated:
#            self._owner.save_model(request, new_object, form, change=False)
#            form.save_m2m()
#            for formset in formsets:
#                self.save_formset(request, form, formset, change=False)
#
#            self._owner.log_addition(request, new_object)
#            return self.response_add(request, new_object)        

    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
        opts = self.model._meta
        app_label = opts.app_label
        ordered_objects = opts.get_ordered_objects()
        context.update({
            'add': add,
            'change': change,
            'has_add_permission': self._owner.has_add_permission(request),
            'has_change_permission': self._owner.has_change_permission(request, obj),
            'has_delete_permission': self._owner.has_delete_permission(request, obj),
            'has_file_field': True, # FIXME - this should check if form or formsets have a FileField,
            'has_absolute_url': hasattr(self.model, 'get_absolute_url'),
            'ordered_objects': ordered_objects,
            'form_url': mark_safe(form_url),
            'opts': opts,
            'content_type_id': ContentType.objects.get_for_model(self.model).id,
            'save_as': self.save_as,
            'save_on_top': self.save_on_top,
            'root_path': self.admin_site.root_path,
        })
        context_instance = template.RequestContext(request, current_app=self.admin_site.name)
        return render_to_response(self.get_change_form_template(), 
                                  context, context_instance=context_instance)
        
    def get_inline_admin_formsets(self, request, adminForm, formsets, obj=None):
        media = self._owner.media + adminForm.media
        
        inline_admin_formsets = []
        for inline, formset in zip(self.inline_instances, formsets):
            fieldsets = list(inline.get_fieldsets(request, obj))
            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media
        
        return inline_admin_formsets, media
    
    def get_change_form_template(self):
        opts = self.model._meta
        app_label = opts.app_label

        return self.change_form_template or [
            "xadmin/change_form.html",
            "2admin/%s/%s/change_form.html" % (app_label, opts.object_name.lower()),
            "2admin/%s/change_form.html" % app_label,
            "2admin/change_form.html"
        ]
